﻿using System.Collections;

namespace Draco.DataStructure
{
    /// <summary>
    /// 链表
    /// </summary>
    /// <typeparam name="T">数据类型</typeparam>
    public class D_LinkList<T> : IEnumerable
    {

        public D_Node<T> Head { get; private set; }
        public int Capacity { get; private set; }

        //public int Count
        //{
        //    get
        //    {
        //        if (Head == null) return 0;
        //        D_Node<T> temp = Head;
        //        int count = 1;
        //        while (true)
        //        {
        //            if (temp.Next != null)
        //            {
        //                count++;
        //                temp = temp.Next;
        //            }
        //            else
        //            {
        //                break;
        //            }
        //        }
        //        return count;
        //    }
        //}

        public int Count { get; private set; }

        public T this[int index]
        {
            get
            {
                if (index < 0 && index >= Count) return default(T);
                D_Node<T> temp = Head;
                for (int i = 1; i <= index; i++)
                {
                    temp = temp.Next;
                }
                return temp.Data;
            }
            set
            {
                D_Node<T> temp = Head;
                for (int i = 1; i <= index; i++)
                {
                    temp = temp.Next;
                }
                temp.Data = value;
                //TODO:超出索引设置的值全设置在了Head数据里面
            }
        }

        public bool IsEmpty()
        {
            return Head == null;
        }

        public void Add(T item)
        {
            D_Node<T> newNode = new D_Node<T>(item);
            if (Head == null)
            {
                Head = newNode;
                Count = 1;
            }
            else
            {
                D_Node<T> temp = Head;
                while (true)
                {
                    if (temp.Next != null)
                    {
                        temp = temp.Next;
                    }
                    else
                    {
                        break;
                    }
                }
                temp.Next = newNode;
                Count++;
            }
        }

        /// <summary>
        /// 批量增加
        /// </summary>
        /// <param name="list">链表</param>
        public void AddRange(D_LinkList<T> list)
        {
            D_Node<T> newNode = list.Head;
            if (Head == null)
            {
                Head = newNode;
                Count = list.Count;
            }
            else
            {
                D_Node<T> temp = Head;
                while (true)
                {
                    if (temp.Next != null)
                    {
                        temp = temp.Next;
                    }
                    else
                    {
                        break;
                    }
                }
                temp.Next = newNode;
                Count += list.Count;
            }
        }

        public void Insert(T item, int index)
        {
            D_Node<T> newNode = new D_Node<T>(item);
            if (index == 0)
            {
                newNode.Next = Head;
                Head = newNode;
            }
            else
            {
                D_Node<T> temp = Head;
                for (int i = 1; i < index; i++)
                {
                    if (temp.Next != null)
                        temp = temp.Next;
                    else
                        break;
                }
                D_Node<T> preNode = temp;
                D_Node<T> curNode = temp.Next;
                preNode.Next = newNode;
                newNode.Next = curNode;
            }
            Count++;
        }

        public T RemoveAt(int index)
        {
            if (index < 0 && index >= Count) return default(T);
            T data = default(T);
            if (index == 0)
            {
                data = Head.Data;
                Head = Head.Next;
            }
            else
            {
                D_Node<T> temp = Head;
                for (int i = 1; i < index; i++)
                {
                    temp = temp.Next;
                }
                D_Node<T> preNode = temp;
                D_Node<T> curNode = temp.Next;
                data = curNode.Data;
                preNode.Next = curNode.Next;
            }
            Count--;
            return data;
        }

        public bool Contains(T item)
        {
            foreach (T VARIABLE in this)
            {
                if (item.Equals(VARIABLE))
                {
                    return true;
                }
            }
            return false;
        }


        public void Clear()
        {
            Head = null;
            Count = 0;
        }


        public IEnumerator GetEnumerator()
        {
            D_Node<T> temp = Head;
            for (int i = 0; i < Count; i++)
            {
                yield return temp.Data;
                temp = temp.Next;
            }
        }
    }
}
